package rs.etf.mips.crossroad.logic;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class Street implements ILogicElement {

	public static final int semaphoreCount = 3;
	public static final int lineCount = 6;

	private List<Line> lines;
	private Light semaphores[];
	private volatile boolean pedestrianArrived;
	
	private PedestrianSemaphore pedestrianSemaphore;

	public Street(double length, double width, double speed) {
		super();
		this.lines = new ArrayList<>(Street.lineCount);
		this.semaphores = new Light[Street.semaphoreCount];
		for (int i = 0; i < lineCount; i++) {
			lines.add(new Line(length, width / Street.lineCount, speed));
		}
		for (int i = 0; i < semaphoreCount; i++) {
			this.lines.get(i).setSemaphore(Light.Off);
		}
		this.pedestrianSemaphore = new PedestrianSemaphore();
		this.pedestrianArrived = true;
	}
	
	public PedestrianSemaphore getPedestrianSemaphore() {
		return pedestrianSemaphore;
	}

	public synchronized boolean isPedestrianArrived() {
		return pedestrianArrived;
	}

	public synchronized void setPedestrianArrived(boolean pedestrianArrived) {
		this.pedestrianArrived = pedestrianArrived;
	}

	/**
	 * Gets the light of the specified semaphore.
	 * 
	 * @param semaphore
	 *            the semaphore ordinal number
	 * @return light of the specified semaphore, or <b>null</b> if the semaphore
	 *         does not exist.
	 */
	public Light getLight(int semaphore) {
		try {
			return semaphores[semaphore];
		} catch (Exception e) {
			return null;
		}
	}

	/**
	 * Sets the light on the specified semaphore.
	 * 
	 * @param light
	 * @param semaphore
	 * @return
	 */
	public boolean setLight(Light light, int semaphore) {
		try {
			this.semaphores[semaphore] = light;
			return true;
		} catch (Exception e) {
			return false;
		}
	}

	/**
	 * Gets the line specified with the <b>lineNumber</b>
	 * 
	 * @param lineNumber
	 *            ordinal number of the line
	 * @return the line specified with the <b>lineNumber</b>, or <b>null</b> if
	 *         the line does not exist.
	 */
	public Line getLine(int lineNumber) {

		Line retVal = null;

		try {
			retVal = lines.get(lineNumber);
		} catch (Exception e) {
		}

		return retVal;
	}

	@Override
	public void update() {
		Iterator<Line> iter = this.lines.iterator();
		while ((iter != null) && (iter.hasNext())) {
			iter.next().update();
		}
	}

	/**
	 * sets out of the unconnected lines to class OutOfBounds
	 */
	public void connectToOutOfBounds(){
		for (Line line : this.lines) {
			if (line.getNeighborTrafficSpace() == null) {
				line.setNeighborTrafficSpace(OutOfBounds.getInstance());
			}
		}
	}
	
	@Override
	public String toString() {
		StringBuffer line = new StringBuffer("Street []");
		Iterator<Line> iter = this.lines.iterator();

		while (iter.hasNext()) {
			line.append("\n\t" + iter.next().toString());
		}

		return line.toString();
	}

	
	
}
